package org.linlinjava.litemall.wx.controller;

import cn.hutool.core.util.StrUtil;
import com.paypal.api.payments.Links;
import com.paypal.api.payments.Payment;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.core.payment.paypal.service.impl.GoodsPaypalServiceImpl;
import org.linlinjava.litemall.core.util.RegexUtil;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.core.validator.Order;
import org.linlinjava.litemall.core.validator.Sort;
import org.linlinjava.litemall.db.beans.Constants;
import org.linlinjava.litemall.db.domain.LitemallGiftCard;
import org.linlinjava.litemall.db.domain.LumierePayMember;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.wx.annotation.LogAnno;
import org.linlinjava.litemall.wx.annotation.LoginUser;
import org.linlinjava.litemall.wx.constant.LitemallWXConstants;
import org.linlinjava.litemall.wx.dto.BuyGiveeMemberDTO;
import org.linlinjava.litemall.wx.dto.GiftCardBuyMemberDTO;
import org.linlinjava.litemall.wx.service.WxPayMemberUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;

import static org.linlinjava.litemall.wx.util.WxResponseCode.*;

/**
 * wx支付成员控制器
 *
 * @author yliyun
 * @date 2022/09/14
 */
@Api(tags = "WX付费会员API")
@RestController
@RequestMapping("/wx/payMember")
@Validated
public class WxPayMemberController {


    /**
     * wx支付会员用户服务
     */
    @Autowired
    private WxPayMemberUserService wxPayMemberUserService;

    /**
     * 订单服务
     */
    @Autowired
    private LitemallOrderService orderService;

    /**
     * GoodsPaypal服务
     */
    @Autowired
    private GoodsPaypalServiceImpl paypalService;

    /**
     * 用户服务
     */
    @Autowired
    private LitemallUserService userService;

    /**
     * Lumiere支付会员服务
     */
    @Autowired
    private LumierePayMemberService lumierePayMemberService;

    /**
     * Lumiere支付会员用户服务
     */
    @Autowired
    private LumierePayMemberUserService lumierePayMemberUserService;

    /**
     * Lumiere支付会员用户日志服务
     */
    @Autowired
    private LumierePayMemberUserLogService lumierePayMemberUserLogService;


    /**
     * litemall礼品卡服务
     */
    @Autowired
    private LitemallGiftCardService litemallGiftCardService;

    /**
     * litemall礼品卡用户服务
     */
    @Autowired
    private LitemallGiftCardUserService litemallGiftCardUserService;

    /**
     * 日志
     */
    private static Log log = LogFactory.getLog(WxPayMemberController.class);


    /**
     * 支付会员列表
     * 查询已上架的所有付费会员信息
     *
     * @param userId 用户id
     * @param shopId 商店id
     * @return {@link Object}
     */
    @GetMapping("listPayMember")
    @LogAnno
    public Object listPayMember(@LoginUser Integer userId,Integer shopId){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        return wxPayMemberUserService.listPayMemberByUser(userId,shopId);
    }

    /**
     * 查看付费会员详情与福利
     *
     * @param userId      用户id
     * @param payMemberId 付费会员id
     * @return {@link Object}
     */
    @GetMapping("payMemberDetail")
    @LogAnno
    public Object payMemberDetail(@LoginUser Integer userId,Integer payMemberId){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        return wxPayMemberUserService.payMemberDetail(userId,payMemberId);
    }

    /**
     * 付费会员日志
     * 用户记录
     *
     * @param userId       用户id
     * @param purchaseType 购买类型
     * @param page         页面
     * @param limit        限制
     * @param sort         排序
     * @param order        订单
     * @return {@link Object}
     */
    @GetMapping("payMemberLog")
    @LogAnno
    public Object payMemberLog(@LoginUser Integer userId,@RequestParam Integer purchaseType,
                               @RequestParam(defaultValue = "1") Integer page,
                               @RequestParam(defaultValue = "10") Integer limit,
                               @Sort @RequestParam(defaultValue = "add_time") String sort,
                               @Order @RequestParam(defaultValue = "desc") String order){
        if(userId == null){
            return ResponseUtil.unlogin();
        }

        return wxPayMemberUserService.payMemberLog(userId,purchaseType,page,limit,sort,order);
    }

    /**
     * 付费会员
     *
     * @param userId   用户id
     * @param memberId 成员身份
     * @param point    积分
     * @param money    钱
     * @param givee    被赠送者
     * @param message  消息
     * @return {@link Object}
     */
    @PutMapping("orderPayMember")
    @LogAnno
    @Transactional
    public Object orderPayMember(@LoginUser Integer userId, @RequestParam Integer memberId, BigDecimal point,BigDecimal money,String givee,String message) {
        if (userId == null) {
            return ResponseUtil.unlogin();
        }

        //根据付费会员允许的购买次数判断是否可以购买
        LumierePayMember payMember =  lumierePayMemberService.findById(memberId);

        Integer count =  lumierePayMemberUserLogService.countMemberUserByMemberId(userId,memberId);

        // 校验礼物卡可购买数量
        for (Integer cardId :payMember.getGiftCardIds()) {
            LitemallGiftCard card = litemallGiftCardService.findById(cardId);
            // 校验礼物卡可购买数量
            Integer saleNum =  (int) litemallGiftCardUserService.sumByCardId(cardId);
            if(card.getNumbers() != 0 && saleNum >= card.getNumbers()){
                return ResponseUtil.fail(CARD_SALED_OVER,"礼物卡已售罄");
            }
        }

        if(payMember.getBuyTimes().equals(0)){
            if(count ==1 ){
                return ResponseUtil.fail(PAYMEMBER_BUY_TIMES_OVER, "用户已购买次数达到该会员购买次数上限");
            }
        }else if(!payMember.getBuyTimes().equals(-1)){
             if(count >= payMember.getBuyTimes()){
                 return ResponseUtil.fail(PAYMEMBER_BUY_TIMES_OVER, "用户已购买次数达到该会员购买次数上限");
             }
        }
        if(point != null && money != null){
            return ResponseUtil.fail(111,"不可同时用金额和积分购买会员");
        }

        if(givee != null ){
            if (!RegexUtil.isMobileValid(givee) && !RegexUtil.isEmailExact(givee)) {
                return ResponseUtil.fail(AUTH_INVALID_MOBILE, "手机号或邮箱格式不正确");
            }
        }

        if(givee != null){
            if(givee.startsWith(MOBILE_CODE_ONE) && RegexUtil.isMobileValid(givee)){
                givee = givee.substring(1,givee.length());
            }
        }

        //接下来根据购买模式购买
        if(point != null){
            //积分购买
            Integer res = (Integer) wxPayMemberUserService.orderPayMemberByPoint(userId, memberId,point,givee);
            return res == Constants.MEMBER_SUCCESS ?
                    wxPayMemberUserService.orderPayMemberSuccess(userId,memberId,point,givee,message)
                    :ResponseUtil.fail(res,"购买会员失败");
        }else{
            //用Paypal购买
            Integer res = (Integer)wxPayMemberUserService.orderPayMemberByMoney(userId,memberId,money,givee);
            return res == Constants.MEMBER_SUCCESS?
                    wxPayMemberUserService.buyMemberByMoney(memberId,money,userId,givee)
                    :ResponseUtil.fail(res,"购买会员失败");
        }
    }

    /**
     * 余额购买付费会员 （给自己买） 存在新购或续购
     *
     * @param userId   用户id
     * @param memberId 成员身份
     * @return {@link ResponseUtil.Response}
     */
    @ApiOperation(value = "余额购买付费会员")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "memberId",value = "付费会员ID"),
            @ApiImplicitParam(name = "money",value = "购买金额")
    })
    @GetMapping(value = {"moneyBuyMember"})
    @LogAnno
    public ResponseUtil.Response moneyBuyMember(@ApiIgnore @LoginUser Integer userId, @RequestParam Integer memberId, BigDecimal money){
        return wxPayMemberUserService.moneyBuyMember(userId,memberId,money);
    }

    /**
     * 余额购买付费会员赠送
     *
     * @param userId                 用户id
     * @param buyGiveeMemberDto 钱买givee成员dto
     * @return {@link ResponseUtil.Response}
     */
    @ApiOperation(value = "余额购买付费会员赠送")
    @PostMapping(value = {"moneyBuyGiveeMember"})
    @LogAnno
    public ResponseUtil.Response moneyBuyGiveeMember(@ApiIgnore @LoginUser Integer userId,@Valid @RequestBody BuyGiveeMemberDTO buyGiveeMemberDto){
        return wxPayMemberUserService.moneyBuyGiveeMember(userId,buyGiveeMemberDto);
    }

    /**
     * 礼物卡购买会员 （给自己买）
     *
     * @param userId               用户id
     * @param giftCardBuyMemberDto 礼品卡购买会员dto
     * @return {@link ResponseUtil.Response}
     */
    @ApiOperation(value = "礼物卡购买会员")
    @PostMapping(value = {"giftCardBuyMember"})
    @LogAnno
    public ResponseUtil.Response giftCardBuyMember(@ApiIgnore @LoginUser Integer userId, @RequestBody GiftCardBuyMemberDTO giftCardBuyMemberDto){
        return wxPayMemberUserService.giftCardBuyMember(userId,giftCardBuyMemberDto);
    }

    /**
     * 礼物卡购买会员赠送
     *
     * @param userId                    用户id
     * @param buyGiveeMemberDto 礼品卡购买givee成员dto
     * @return {@link ResponseUtil.Response}
     */
    @ApiOperation(value = "礼物卡购买会员赠送")
    @PostMapping(value = {"giftCardBuyGiveeMember"})
    @LogAnno
    public ResponseUtil.Response giftCardBuyGiveeMember(@ApiIgnore @LoginUser Integer userId,@RequestBody BuyGiveeMemberDTO buyGiveeMemberDto){
        return wxPayMemberUserService.giftCardBuyGiveeMember(userId,buyGiveeMemberDto);
    }


    /**
     * 付款准备
     *
     * @param userId   用户id
     * @param orderId  订单id
     * @param memberId 成员身份
     * @param resp     分别地
     * @param givee    givee
     * @param message  消息
     * @return {@link Object}
     * @throws Exception 异常
     */
    @GetMapping("payAfterSuccess")
    @LogAnno
    public Object payAfterSuccess(@LoginUser Integer userId, @NotNull Integer orderId,@NotNull Integer memberId, HttpServletResponse resp, String givee,String message) throws Exception{
        if(givee.startsWith(MOBILE_CODE_ONE) && RegexUtil.isMobileValid(givee)){
            givee = givee.substring(1,givee.length());
        }
        Object obj =  wxPayMemberUserService.getPayment(orderId,givee,memberId,message);
        if(!(obj instanceof Payment)){
            return obj;
        }
        Payment payment = (Payment)obj;
        for(Links links : payment.getLinks()){
            if(links.getRel().equals("approval_url")){
                resp.sendRedirect(links.getHref().toString());
                return "redirect:" + links.getHref();
            }
        }
        return "<script type=\"text/javascript\">location.href=\"/\"</script>" ;
    }


    /**
     * 成功
     * 付款完成
     *
     * @param userId    用户id
     * @param paymentId 支付id
     * @param payerId   付款人身份
     * @param resp      分别地
     * @param request   请求
     * @return {@link Object}
     * @throws Exception 异常
     */
    @GetMapping("pay/success")
    @LogAnno
    public Object success(@LoginUser Integer userId, @NotNull @RequestParam("paymentId") String paymentId,@NotNull @RequestParam("PayerID") String payerId, HttpServletResponse resp, HttpServletRequest request) throws Exception{
        log.debug("paypal success");
        log.debug("更新订单信息之前");
        Object obj =  wxPayMemberUserService.executePayment(paymentId, payerId);
        log.debug("更新订单信息成功");
        if(!(obj instanceof Payment)){
            return obj;
        }
        Payment payment = (Payment)obj;
        String userName = request.getParameter("userName");
        Integer memberId = Integer.valueOf(request.getParameter("memberId"));

        /*LitemallOrder order = orderService.findByOutTradeNo(paymentId);
        paypalService.presentPoint(order.getId(),null);
        //用户 等级会员的提升
        paypalService.upgradeUserLevel(order.getId());*/
        return wxPayMemberUserService.success(payment,userName,memberId,userId,paymentId);
    }

    /**
     * 取消支付
     *
     * @return {@link Object}
     */
    @PostMapping("pay/cancel")
    @LogAnno
    public Object cancelPay(){
        return ResponseUtil.ok("cancel") ;
    }
}
